package cn.njxzc.book.masterexamples.ch17;

import java.util.*;

public class Generic<T> {

	private T f; // f为泛型成员
	private T[] array; // 此处不能用new T[]实例化array

	public void setF(T f) {// setF方法的参数类型为泛型T
		this.f = f;
	}

	public T getF() {// getF方法的返回类型为泛型T
		return f;
	}

	public void setArray(T[] array) {
		this.array = array;
	}

	public T[] getArray() {
		return array;
	}

	void doSome() {
		/*
		 * getClass和toString都是Object中的方法
		 */
		System.out.println(f.getClass().getName());
		System.out.println(f.toString());
	}

	public static void main(String[] args) {
		/*-------------------------------------*/	
		Generic<Boolean> f1 = new Generic<Boolean>();
		// f2中的泛型T在此指定为Integer类型
		Generic<Integer> f2 = new Generic<Integer>();
		// f1的setF方法只能接受Boolean类型数据
		f1.setF(new Boolean(true));
		Boolean b = f1.getF();
		System.out.println(b);
		// f2的setF方法只能接受Integer类型的数据
		f2.setF(new Integer(10));
		Integer i = f2.getF();
		System.out.println(i);
		/*-------------------------------------*/	
		// 实例化时的泛型的默认类型
		Generic f3 = new Generic();
		System.out.println(f3.getClass().getName());
		f3.setF(new Boolean(false));
		//Generic<Object> f4=f1; 
		

		
		
		// 建立类型为泛型类的数组
		Generic<String>[] gs; // 声明泛型类的数组
		// 先对泛型数组进行初始化
		gs = new Generic[5]; // 不要写成new Generic<String>[5]
		// 再分别为每一个数组元素进行初始化
		gs[0] = new Generic<String>();// 为第一个数组元素赋值
		// 向泛型成员array传递实际的字符串数组
		String[] strs = { "caterpillar", "momor", "bush" };
		Generic<String> f = new Generic<String>();
		// 读取泛型成员array的值，将其赋给字符串数组变量strs
		// 此时array的类型为字符串数组

		f.setArray(strs);
		strs = f.getArray();
		System.out.println(strs);
	
/*-------------------------------------*/	
		Generic<?>   f5;
		f5=f1;
		f5=f2;
		f5=f3;
		Generic<? extends List> f6= null;
		f6 = new Generic<ArrayList>(); //Ok
		 
		f6 = new Generic<Vector>();  //OK
		
		//以下语句会发生编译错误，因为HashMap没有实现List接口
		//f6 = new Genric<HashMap>();
	
		//将f限定为只能代表采用java.sql.Date的父类实例化的实例
		Generic<? super java.sql.Date> f7 = null;
		f7=new Generic<java.sql.Date>(); //Ok

		//Ok,java.util.Date是java.sql.Date的父类
		f7=new Generic<java.util.Date>(); 

		//错误，因为String不是java.sql.Date的父类
	//	f7=new Generic<String>();

	//	一旦对象使用通配字符声明，就无法利用它为类中的泛型成员传入新的实例，这时只能读取其中的泛型成员或者移除泛型成员存储的原有实例。

	
		Generic<String> f8 = new Generic<String>();
		f8.setF("caterpillar");
		Generic<?> immutableF = f8;
		//可读取泛型成员f中保存的字符串实例
		System.out.println(immutableF.getF());

		//可通过传递null参数来移除泛型成员f中保存的字符串实例
		immutableF.setF(null);

		//不能通过immutableF的setF方法再次传递新的实例给类中
		//泛型成员f,所以下面这行无法通过编译
	//	immutableF.setF("wang");

		
		
		/*--实例化泛型类时采用默认泛型类型，此时泛型类的实例和其他给定类型的泛型类实例之间存在着类型兼容性，可以直接相互赋值。--*/
		Generic f9 = new Generic();//默认泛型类型
		f9  = f1;  //OK
		f9  = f2;  //OK
		f1 = f9;  //OK
		f2 = f9;  //OK 

	
	
	}

}
